package me.flyray.bsin.infrastructure.biz;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.blockchain.config.BlockchainProperties;
import me.flyray.bsin.blockchain.transaction.BlockchainTransactionService;
import me.flyray.bsin.blockchain.transaction.SmartGasFeeService;
import me.flyray.bsin.blockchain.connection.Web3jConnectionPoolService;
import me.flyray.bsin.domain.entity.Wallet;
import me.flyray.bsin.domain.entity.WalletAccount;
import me.flyray.bsin.domain.entity.ChainCoin;
import me.flyray.bsin.domain.enums.AccountCategory;
import me.flyray.bsin.domain.enums.CcyType;
import me.flyray.bsin.facade.service.AccountService;
import me.flyray.bsin.infrastructure.mapper.WalletAccountMapper;
import me.flyray.bsin.infrastructure.mapper.WalletMapper;
import me.flyray.bsin.infrastructure.mapper.ChainCoinMapper;
import me.flyray.bsin.mq.enums.MqEventCode;
import me.flyray.bsin.mq.producer.RocketMQProducer;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.EthTransaction;
import org.web3j.protocol.core.methods.response.Transaction;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.utils.Numeric;
import org.web3j.crypto.Hash;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;

/**
 * 区块链资金归集业务服务
 * 提供资金归集的完整流程管理，包括加油、归集、确认等
 */
@Slf4j
@Service
public class BlockchainFundCollectionBiz {

    @Autowired
    private BlockchainTransactionService blockchainTransactionService;

    @Autowired
    private BlockchainProperties blockchainProperties;
    
    @Autowired
    private SmartGasFeeService smartGasFeeService;
    
    @Autowired
    private Web3jConnectionPoolService web3jConnectionPoolService;

    @Autowired
    private RocketMQProducer rocketMQProducer;

    @Value("${rocketmq.consumer.topic}")
    private String topic;

    @Autowired
    private WalletAccountMapper walletAccountMapper;
    @Autowired
    private WalletMapper walletMapper;
    @Autowired
    private ChainCoinMapper chainCoinMapper;
    @DubboReference(version = "${dubbo.provider.version}")
    private AccountService accountService;

    /**
     * 启动资金归集流程 - 核心业务逻辑
     * 完整流程：
     * 1. 验证归集参数和配置
     * 2. 给用户账户提供gas费用
     * 3. 放入延时队列等待gas交易确认
     * 4. 后续通过MQ消息处理gas确认和代币归集
     * 
     * @param chainIdentifier 链标识
     * @param fromAddress 用户地址
     * @param gatherAccountAddress 归集地址
     * @param contractAddress 代币合约地址
     * @param amount 归集金额
     * @param decimals 代币精度
     */
    public void startFundCollectionProcess(String chainIdentifier, String fromAddress, String gatherAccountAddress,
                                          String contractAddress, BigInteger amount, Integer decimals) {
        log.info("启动区块链资金归集流程: chain={}, from={}, amount={}", chainIdentifier, fromAddress, amount);

        try {
            // 验证gas配置
            BlockchainProperties.GasFeeConfig gasFeeConfig = blockchainProperties.getGasFee();
            if (gasFeeConfig == null || gasFeeConfig.getAddress() == null || gasFeeConfig.getPrivateKey() == null) {
                log.error("gas配置验证失败，配置信息不完整");
                throw new RuntimeException("gas配置信息不完整，无法进行资金归集");
            }

            // 给用户账户提供gas
            String gasTxHash = executeGasProvisionToUser(chainIdentifier, fromAddress);
            log.debug("用户gas提供完成: gasTxHash={}", gasTxHash);

            // 调度延时队列等待gas确认
            scheduleGasTransactionConfirmationCheck(chainIdentifier, gasTxHash, fromAddress, gatherAccountAddress, contractAddress, amount, decimals);

        } catch (Exception e) {
            log.error("启动资金归集流程失败: chain={}, from={}, error={}",
                    chainIdentifier, fromAddress, e.getMessage(), e);
            throw new RuntimeException("启动资金归集流程失败: " + e.getMessage(), e);
        }
    }

    /**
     * 处理gas确认事件 - 关键异步处理步骤
     * 流程步骤：
     * 1. 查询gas交易状态确认
     * 2. 如果成功则执行代币归集
     * 3. 如果失败则重新触发整个流程
     * 4. 调度归集确认监听
     * 
     * @param chainIdentifier 链名称
     * @param gasTxHash 加油交易哈希
     * @param fromAddress 用户地址
     * @param toAddress 归集地址
     * @param contractAddress 代币合约地址
     * @param amount 归集金额
     * @param decimals 代币精度
     */
    public void handleGasTransactionConfirmationEvent(String chainIdentifier, String gasTxHash, String fromAddress,
                                     String toAddress, String contractAddress, BigInteger amount, Integer decimals) {
        log.info("处理gas确认事件: chain={}, gasTxHash={}, from={}, amount={}", 
                chainIdentifier, gasTxHash, fromAddress, amount);

        try {
            
            // 查询gas交易状态
            TransactionReceipt gasReceipt = null;
            try {
                gasReceipt = blockchainTransactionService.getTransactionReceipt(chainIdentifier, gasTxHash);
            } catch (Exception e) {
                log.warn("首次查询gas交易异常: gasTxHash={}, error={}", gasTxHash, e.getMessage());
            }
            
            // 如果首次查询为空，尝试带重试的查询
            if (gasReceipt == null) {
                try {
                    gasReceipt = blockchainTransactionService.getTransactionReceiptWithRetry(chainIdentifier, gasTxHash, 2, 2000);
                } catch (Exception e) {
                    log.warn("重试查询gas交易也失败: gasTxHash={}, error={}", gasTxHash, e.getMessage());
                }
            }
            
            if (gasReceipt == null) {
                log.warn("gas交易收据查询为空，重新调度: gasTxHash={}", gasTxHash);
                scheduleGasTransactionConfirmationCheck(chainIdentifier, gasTxHash, fromAddress, toAddress, contractAddress, amount, decimals);
                return;
            }

            if (gasReceipt.isStatusOK()) {
                log.info("gas交易成功，开始执行代币归集: from={}, amount={}", fromAddress, amount);

                // 根据地址查询私钥
                LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(WalletAccount::getAddress, fromAddress);
                WalletAccount fromWalletAccount = walletAccountMapper.selectOne(queryWrapper);
                String collectionTxHash;
                try {
                    // 查询钱包账户的钱包类型
                    Wallet wallet = walletMapper.selectById(fromWalletAccount.getWalletNo());
                    collectionTxHash = blockchainTransactionService.tokenTransfer(
                            chainIdentifier, fromAddress, wallet.getType(), fromWalletAccount.getPrivateKey(), toAddress, contractAddress, amount, decimals);

                    log.info("代币归集交易已提交: collectionTxHash={}", collectionTxHash);
                    scheduleFundCollectionConfirmationTask(chainIdentifier, collectionTxHash);
                    
                } catch (Exception transferException) {
                    log.error("代币转账失败: chain={}, from={}, amount={}, error={}", 
                            chainIdentifier, fromAddress, amount, transferException.getMessage());
                    
                    String errorMessage = transferException.getMessage();
                    if (errorMessage != null) {
                        if (errorMessage.contains("Gas 估算失败") && errorMessage.contains("execution reverted")) {
                            log.error("转账失败：合约调用被回滚，可能余额不足或授权问题");
                        }
                    }

                    // 重新调度gas确认
                    scheduleGasTransactionConfirmationCheck(chainIdentifier, gasTxHash, fromAddress, toAddress, contractAddress, amount, decimals);
                    return;
                }
                
            } else {
                log.error("gas交易执行失败，重新启动归集流程: gasTxHash={}, status={}", 
                        gasTxHash, gasReceipt.isStatusOK());
                startFundCollectionProcess(chainIdentifier, fromAddress, toAddress, contractAddress, amount, decimals);
            }

        } catch (Exception e) {
            log.error("gas确认处理异常: gasTxHash={}, error={}", gasTxHash, e.getMessage(), e);
            scheduleGasTransactionConfirmationCheck(chainIdentifier, gasTxHash, fromAddress, toAddress, contractAddress, amount, decimals);
        }
    }

    /**
     * 处理资金归集确认事件 - 最终确认步骤
     * 流程步骤：
     * 1. 查询归集交易最终状态
     * 2. 根据交易结果发送成功/失败通知
     * 3. 更新相关业务状态
     * 
     * @param chainIdentifier 链标识
     * @param collectionTxHash 归集交易哈希
     */
    public void handleFundCollectionConfirmationEvent(String chainIdentifier, String collectionTxHash) {
        log.info("处理资金归集确认事件: chain={}, collectionTxHash={}", chainIdentifier, collectionTxHash);

        try {
            // 查询归集交易最终状态
            TransactionReceipt collectionReceipt = null;
            try {
                collectionReceipt = blockchainTransactionService.getTransactionReceipt(chainIdentifier, collectionTxHash);
            } catch (Exception e) {
                log.warn("首次查询归集交易异常: collectionTxHash={}, error={}", collectionTxHash, e.getMessage());
            }
            
            // 如果首次查询为空，尝试带重试的查询
            if (collectionReceipt == null) {
                try {
                    collectionReceipt = blockchainTransactionService.getTransactionReceiptWithRetry(chainIdentifier, collectionTxHash, 2, 3000);
                } catch (Exception e) {
                    log.warn("重试查询归集交易也失败: collectionTxHash={}, error={}", collectionTxHash, e.getMessage());
                }
            }
            
            if (collectionReceipt == null) {
                log.warn("归集交易收据查询为空，重新调度: collectionTxHash={}", collectionTxHash);
                scheduleFundCollectionConfirmationTask(chainIdentifier, collectionTxHash);
                return;
            }

            if (collectionReceipt.isStatusOK()) {
                log.info("资金归集交易执行成功: collectionTxHash={}", collectionTxHash);
                notifyFundCollectionSuccessEvent(chainIdentifier, collectionTxHash, collectionReceipt);
            } else {
                log.error("资金归集交易执行失败: collectionTxHash={}, status={}", 
                        collectionTxHash, collectionReceipt.isStatusOK());
                String errorMessage = String.format("归集交易执行失败，交易状态：%s", collectionReceipt.isStatusOK());
                notifyFundCollectionFailureEvent(chainIdentifier, collectionTxHash, errorMessage);
            }

        } catch (Exception e) {
            log.error("归集确认处理异常: collectionTxHash={}, error={}", collectionTxHash, e.getMessage(), e);
            scheduleFundCollectionConfirmationTask(chainIdentifier, collectionTxHash);
        }
    }

    /**
     * 给用户账户提供 Gas 费用 - 关键步骤
     * 流程：
     * 1. 获取gas提供者配置
     * 2. 动态计算gas数量
     * 3. 执行ETH转账提供gas
     * 
     * @param chainIdentifier 链名称
     * @param userAddress 用户地址
     * @return 加油交易哈希
     */
    private String executeGasProvisionToUser(String chainIdentifier, String userAddress) throws Exception {
        log.info("开始给用户提供Gas费用: chain={}, address={}", chainIdentifier, userAddress);

        // 获取gas提供者配置
        BlockchainProperties.GasFeeConfig gasFeeConfig = blockchainProperties.getGasFee();
        String gasProviderAddress = gasFeeConfig.getAddress();
        String gasProviderAddressPrivateKey = gasFeeConfig.getPrivateKey();
        
        // 动态计算gas数量
        BigInteger gasAmount = calculateDynamicGasAmount(chainIdentifier, gasFeeConfig);
        
        // 执行ETH转账提供gas
        String gasTxHash = blockchainTransactionService.ethTransfer(chainIdentifier, gasProviderAddress, gasProviderAddressPrivateKey, userAddress, gasAmount);
        
        log.info("Gas费用提供完成: chain={}, amount={}, txHash={}", chainIdentifier, gasAmount, gasTxHash);
        
        return gasTxHash;
    }
    
    /**
     * 动态计算gas amount - 优化版本
     * 通过网络状态和配置来决定发送给用户的gas数量
     * 
     * 优化策略：
     * 1. 基于实时gas价格计算精确的代币转账费用
     * 2. 根据网络拥堵状况动态调整gas价格
     * 3. 设置合理的边界值和安全倍数
     * 4. 支持不同链的差异化配置
     */
    private BigInteger calculateDynamicGasAmount(String chainName, BlockchainProperties.GasFeeConfig gasFeeConfig) {
        log.info("开始动态计算gas费用: chain={}", chainName);
        
        try {
            // 获取网络连接和gas价格信息
            Web3j web3j = web3jConnectionPoolService.getHttpConnection(chainName);
            SmartGasFeeService.GasPriceInfo gasPriceInfo = smartGasFeeService.getSmartGasPrice(chainName, web3j, "normal");
            
            if (gasPriceInfo == null) {
                throw new RuntimeException("无法获取gas价格信息");
            }
            
            // 获取链特定的计算参数
            GasCalculationParams params = getGasCalculationParams(chainName);
            
            // 智能选择gas价格：优先使用合理的价格，避免过高或过低
            BigInteger gasPrice;
            if (gasPriceInfo.isEIP1559) {
                // EIP-1559: 使用maxFeePerGas，但确保不会过高
                gasPrice = gasPriceInfo.maxFeePerGas;
                // 如果优先费用过高，使用传统gasPrice作为备选
                if (gasPriceInfo.maxPriorityFeePerGas.compareTo(gasPriceInfo.gasPrice) > 0) {
                    BigInteger maxReasonablePrice = gasPriceInfo.gasPrice.multiply(BigInteger.valueOf(2));
                    if (gasPrice.compareTo(maxReasonablePrice) > 0) {
                        gasPrice = maxReasonablePrice;
                        log.debug("gas价格过高，使用调整后的价格: {}", gasPrice);
                    }
                }
            } else {
                // 传统模式：直接使用gasPrice
                gasPrice = gasPriceInfo.gasPrice;
            }
            
            // 计算基础gas费用 - 使用实际估算的gas limit而不是固定的边界值
            // 这里我们提供的是实际预估费用 + 小的安全边际，而不是按最大边界值提供
            BigInteger singleTransferCost = gasPrice.multiply(BigInteger.valueOf(params.gasLimitPerTransfer));
            BigInteger totalBaseCost = singleTransferCost.multiply(BigInteger.valueOf(params.estimatedTransferCount));
            
            log.debug("gas计算: price={}, limit={}, transfers={}, baseCost={}", 
                    gasPrice, params.gasLimitPerTransfer, params.estimatedTransferCount, totalBaseCost);
            
            // 应用安全倍数 - 但不要太激进，只提供必要的小额缓冲
            BigInteger finalGasAmount = totalBaseCost.multiply(BigInteger.valueOf(params.safetyMultiplier))
                    .divide(BigInteger.valueOf(100));
            
            // 获取边界限制，但只作为上限保护，不强制使用最大值
            GasBoundaryParams boundary = getGasBoundaryParams(chainName);
            
            // 确保最小值 - 防止过少
            if (finalGasAmount.compareTo(boundary.minAmount) < 0) {
                finalGasAmount = boundary.minAmount;
                log.debug("gas费用低于最小值，使用最小值: {}", finalGasAmount);
            } 
            // 只在上限确实不足时才使用最大值，否则使用计算值避免浪费
            else if (finalGasAmount.compareTo(boundary.maxAmount) > 0) {
                // 检查计算值是否真的超出合理范围
                BigInteger reasonableMax = singleTransferCost.multiply(BigInteger.valueOf(120)).divide(BigInteger.valueOf(100)); // 20%缓冲
                if (reasonableMax.compareTo(boundary.maxAmount) <= 0) {
                    finalGasAmount = reasonableMax;
                    log.debug("使用合理上限避免浪费: {} -> {}", boundary.maxAmount, finalGasAmount);
                } else {
                    finalGasAmount = boundary.maxAmount;
                    log.warn("gas费用超出边界上限，使用最大值: {}", finalGasAmount);
                }
            }
            
            log.info("gas费用计算完成: chain={}, amount={}, price={}", chainName, finalGasAmount, gasPrice);
            return finalGasAmount;
            
        } catch (Exception e) {
            log.error("动态计算gas费用失败，使用配置默认值: chain={}, error={}", chainName, e.getMessage());
            BigInteger fallbackAmount = BigInteger.valueOf(gasFeeConfig.getAmount());
            log.info("使用配置默认gas费用: {}", fallbackAmount);
            return fallbackAmount;
        }
    }

    /**
     * 获取gas计算参数 - 根据链类型优化配置
     * 基于实际ERC20代币转账需求进行精确计算
     */
    private GasCalculationParams getGasCalculationParams(String chainName) {
        GasCalculationParams params = new GasCalculationParams();
        
        switch (chainName.toLowerCase()) {
            case "ethereum":
                // Ethereum: ERC20转账实际可能需要更多gas，特别是网络拥堵时
                // 实际测试发现需要约100k-120k gas用于ERC20转账
                params.gasLimitPerTransfer = 100000; // 增加到100k，更符合实际情况
                params.estimatedTransferCount = 1;  // 通常只需要1次代币转账
                params.safetyMultiplier = 115; // 降低到115%，减少浪费但保证安全
                break;
            case "bsc":
            case "bnb":
                // BSC: ERC20转账实际也需要更多gas，网络拥堵时可能达到80k-100k
                params.gasLimitPerTransfer = 80000; // 增加到80k，更符合实际情况
                params.estimatedTransferCount = 1;
                params.safetyMultiplier = 120; // 降低到120%，减少浪费
                break;
            case "polygon":
            case "matic":
                // Polygon: ERC20转账实际也需要更多gas，虽然费用低但gas limit仍需要合理设置
                params.gasLimitPerTransfer = 70000; // 增加到70k，更符合实际情况
                params.estimatedTransferCount = 1;
                params.safetyMultiplier = 125; // 降低到125%，Polygon费用低可以稍微高一点
                break;
            case "tron":
                // TRON: 使用不同的fee机制
                params.gasLimitPerTransfer = 0; // TRON不使用gas limit
                params.estimatedTransferCount = 1;
                params.safetyMultiplier = 200;
                break;
            default:
                // 默认配置：保守估算，使用较高的gas limit
                params.gasLimitPerTransfer = 80000; // 提高默认gas limit
                params.estimatedTransferCount = 1;
                params.safetyMultiplier = 120; // 降低到120%，避免浪费
                log.warn("使用默认gas计算参数: chain={}", chainName);
                break;
        }
        
        return params;
    }

    /**
     * 获取gas边界参数 - 根据链类型设置合理的边界值
     */
    private GasBoundaryParams getGasBoundaryParams(String chainName) {
        GasBoundaryParams boundary = new GasBoundaryParams();
        
        switch (chainName.toLowerCase()) {
            case "ethereum":
                // Ethereum: 基于100k gas limit * 1转账 * 150%安全系数，按50 gwei gas价格计算
                // 约 100,000 * 50 * 10^9 * 1 * 1.5 = 7.5 * 10^15 Wei ≈ 0.0075 ETH
                boundary.minAmount = BigInteger.valueOf(2000000000000000L);    // 0.002 ETH (Wei) - 提高最小值
                boundary.maxAmount = BigInteger.valueOf(15000000000000000L);   // 0.015 ETH (Wei) - 大幅提高最大值
                break;
            case "bsc":
            case "bnb":
                // BSC: 基于80k gas limit * 1转账 * 150%安全系数，按10 gwei gas价格计算
                // 约 80,000 * 10 * 10^9 * 1 * 1.5 = 1.2 * 10^15 Wei ≈ 0.0012 BNB
                boundary.minAmount = BigInteger.valueOf(500000000000000L);     // 0.0005 BNB (Wei)
                boundary.maxAmount = BigInteger.valueOf(8000000000000000L);    // 0.008 BNB (Wei) - 提高最大值
                break;
            case "polygon":
            case "matic":
                // Polygon: 基于70k gas limit * 1转账 * 180%安全系数，按50 gwei gas价格计算
                // 约 70,000 * 50 * 10^9 * 1 * 1.8 = 6.3 * 10^15 Wei ≈ 0.0063 MATIC
                boundary.minAmount = BigInteger.valueOf(3000000000000000L);    // 0.003 MATIC (Wei) - 提高最小值
                boundary.maxAmount = BigInteger.valueOf(25000000000000000L);   // 0.025 MATIC (Wei) - 提高最大值
                break;
            default:
                // 默认边界值：基于80k gas limit * 1转账 * 180%安全系数
                boundary.minAmount = BigInteger.valueOf(1000000000000000L);     // 0.001 ETH (Wei) - 提高最小值
                boundary.maxAmount = BigInteger.valueOf(15000000000000000L);    // 0.015 ETH (Wei) - 提高最大值
                break;
        }
        
        return boundary;
    }

    /**
     * Gas计算参数类
     */
    private static class GasCalculationParams {
        int gasLimitPerTransfer = 60000;    // 每次代币转账的gas limit
        int estimatedTransferCount = 2;     // 预估需要的转账次数
        int safetyMultiplier = 200;         // 安全倍数（百分比，200表示2倍）
    }

    /**
     * Gas边界参数类
     */
    private static class GasBoundaryParams {
        BigInteger minAmount;  // 最小gas金额
        BigInteger maxAmount;  // 最大gas金额
    }

    /**
     * 调度Gas确认检查 - 延时队列处理
     * 将Gas确认任务放入延时队列等待确认，确认成功后触发资金归集
     */
    private void scheduleGasTransactionConfirmationCheck(String chainIdentifier, String gasTxHash, String fromAddress,
                                       String gatherAccountAddress, String contractAddress, BigInteger amount, Integer decimals) {
        log.info("调度Gas确认检查: chain={}, gasTxHash={}", chainIdentifier, gasTxHash);
        
        try {
            // 验证必要参数
            if (topic == null || topic.trim().isEmpty()) {
                log.error("MQ Topic配置为空，无法发送消息");
                throw new IllegalArgumentException("MQ Topic配置不能为空");
            }
            
            if (rocketMQProducer == null) {
                log.error("RocketMQProducer未初始化");
                throw new IllegalStateException("RocketMQProducer未初始化");
            }
            
            // 构造MQ消息
        JSONObject mqMessage = new JSONObject();
        mqMessage.put("chainIdentifier", chainIdentifier);
        mqMessage.put("gasTxHash", gasTxHash);
        mqMessage.put("fromAddress", fromAddress);
        mqMessage.put("toAddress", gatherAccountAddress);
        mqMessage.put("contractAddress", contractAddress);
        mqMessage.put("amount", amount.toString());
        mqMessage.put("decimals", decimals.toString());
        mqMessage.put("eventCode", MqEventCode.GET_GAS_NOTIFY.getCode());
        mqMessage.put("timestamp", System.currentTimeMillis());
        mqMessage.put("retryCount", 0);
            
        String messageBody = mqMessage.toString();
        
        // 检查消息大小（避免超过限制）
        int messageSize = messageBody.getBytes().length;
        log.info("准备发送MQ延时消息: gasTxHash={}, topic={}, messageSize={} bytes", gasTxHash, topic, messageSize);
        
        if (messageSize > 1048576) { // 1MB限制
            log.error("消息体过大: gasTxHash={}, size={} bytes, limit=1048576 bytes", gasTxHash, messageSize);
            throw new IllegalArgumentException("消息体过大，超过1MB限制");
        }

        // 延时消息等级分为18个：1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
        // 使用等级4（约30秒）等待gas确认
        int delayLevel = 4;

        // 尝试发送延时消息，添加异常捕获和重试机制
        try {
            rocketMQProducer.sendDelay(topic, messageBody, new org.apache.rocketmq.client.producer.SendCallback() {
            @Override
            public void onSuccess(org.apache.rocketmq.client.producer.SendResult sendResult) {
                        log.info("Gas确认检查任务调度成功: gasTxHash={}, msgId={}", gasTxHash, sendResult.getMsgId());
            }
            @Override
            public void onException(Throwable throwable) {
                        log.error("Gas确认检查任务调度失败: gasTxHash={}, error={}, stackTrace={}", 
                            gasTxHash, 
                            throwable.getMessage() != null ? throwable.getMessage() : throwable.getClass().getName(),
                            throwable);
                    }
                }, delayLevel);
                
            } catch (Exception sendException) {
                log.error("发送延时消息失败: topic={}, gasTxHash={}, error={}", topic, gasTxHash, sendException.getMessage(), sendException);
                throw sendException;
            }
            
        } catch (Exception e) {
            log.error("调度Gas确认检查任务异常: gasTxHash={}, chainIdentifier={}, error={}", 
                gasTxHash, chainIdentifier, e.getMessage(), e);
            throw new RuntimeException("调度Gas确认检查任务失败: " + e.getMessage(), e);
        }
    }

    /**
     * 调度资金归集确认
     * 将归集确认任务放入延时队列
     */
    private void scheduleFundCollectionConfirmationTask(String chainIdentifier, String collectionTxHash) {
        JSONObject mqMessage = new JSONObject();
        mqMessage.put("chainIdentifier", chainIdentifier);
        mqMessage.put("collectionTxHash", collectionTxHash);
        mqMessage.put("eventCode", MqEventCode.CASH_CONCENTRATION_NOTIFY.getCode());

        // 使用等级4（约2分钟）等待归集确认
        rocketMQProducer.sendDelay(topic, mqMessage.toString(), new org.apache.rocketmq.client.producer.SendCallback() {
            @Override
            public void onSuccess(org.apache.rocketmq.client.producer.SendResult sendResult) {
                log.info("资金归集确认任务调度成功");
            }
            @Override
            public void onException(Throwable throwable) {
                log.error("资金归集确认任务调度失败", throwable);
            }
        }, 4);
    }

    /**
     * 通知归集成功
     * 通知商户或平台归集成功，进行自己的业务处理
     */
    private void notifyFundCollectionSuccessEvent(String chainIdentifier, String collectionTxHash, TransactionReceipt receipt) {
        log.info("资金归集成功通知，chain: {}, txHash: {}, blockNumber: {}",
                chainIdentifier, collectionTxHash, receipt.getBlockNumber());
        
        try {
            // 通过交易哈希获取交易详情，用于CRM充值
            executeCrmRechargeFromCollectionResult(chainIdentifier, collectionTxHash, receipt);
        } catch (Exception e) {
            log.error("归集成功后CRM充值失败: chain={}, txHash={}", chainIdentifier, collectionTxHash, e);
        }
    }

    /**
     * 从归集交易中提取信息并进行CRM充值
     */
    private void executeCrmRechargeFromCollectionResult(String chainIdentifier, String collectionTxHash, TransactionReceipt receipt) {
        try {
            // 获取交易详情
            Web3j web3j = web3jConnectionPoolService.getHttpConnection(chainIdentifier);
            EthTransaction ethTransaction = web3j.ethGetTransactionByHash(collectionTxHash).send();
            
            if (!ethTransaction.getTransaction().isPresent()) {
                log.warn("无法获取交易详情: txHash={}", collectionTxHash);
                return;
            }
            
            Transaction transaction = ethTransaction.getTransaction().get();
            String fromAddress = transaction.getFrom();
            
            // 查找用户钱包信息
            LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WalletAccount::getAddress, fromAddress);
            WalletAccount fromWalletAccount = walletAccountMapper.selectOne(queryWrapper);
            
            if (fromWalletAccount == null) {
                log.warn("未找到用户钱包账户: fromAddress={}", fromAddress);
                return;
            }
            
            // 查找钱包配置信息
            Wallet wallet = walletMapper.selectById(fromWalletAccount.getWalletNo());
            if (wallet == null) {
                log.warn("未找到钱包配置: walletNo={}", fromWalletAccount.getWalletNo());
                return;
            }
            
            // 解析交易金额（原始Wei值）
            BigDecimal rawTxAmount = parseTokenAmountFromTransaction(transaction, receipt);
            if (rawTxAmount == null || rawTxAmount.compareTo(BigDecimal.ZERO) <= 0) {
                log.warn("无法解析有效交易金额，跳过处理: txHash={}", collectionTxHash);
                return;
            }
            
            // 获取代币合约信息以确定精度
            // 对于ERC20转账，transaction.getTo()是代币合约地址
            String contractAddress = transaction.getTo(); 
            ChainCoin chainCoin = null;
            if (contractAddress != null) {
                LambdaQueryWrapper<ChainCoin> coinQueryWrapper = new LambdaQueryWrapper<>();
                coinQueryWrapper.eq(ChainCoin::getContractAddress, contractAddress);
                coinQueryWrapper.eq(ChainCoin::getStatus, 1); // 上架状态
                chainCoin = chainCoinMapper.selectOne(coinQueryWrapper);
                
                if (chainCoin == null) {
                    // 如果没找到，尝试从Transfer事件日志中获取合约地址
                    String logContractAddress = getTokenContractAddressFromLogs(receipt);
                    if (logContractAddress != null) {
                        coinQueryWrapper = new LambdaQueryWrapper<>();
                        coinQueryWrapper.eq(ChainCoin::getContractAddress, logContractAddress);
                        coinQueryWrapper.eq(ChainCoin::getStatus, 1);
                        chainCoin = chainCoinMapper.selectOne(coinQueryWrapper);
                        contractAddress = logContractAddress;
                    }
                }
            }
            
            // 根据代币精度转换金额
            BigDecimal txAmount;
            if (chainCoin != null && chainCoin.getCoinDecimal() != null) {
                int decimals = chainCoin.getCoinDecimal().intValue();
                // 检查精度值是否合理
                if (decimals < 0 || decimals > 255) {
                    log.warn("币种精度值异常，使用默认值18: decimals={}", decimals);
                    decimals = 18;
                }
                txAmount = rawTxAmount.divide(BigDecimal.TEN.pow(decimals));
                log.debug("按精度转换金额: rawAmount={}, decimals={}, convertedAmount={}", 
                        rawTxAmount, decimals, txAmount);
            } else {
                // 如果找不到代币配置，使用默认精度18
                txAmount = rawTxAmount.divide(BigDecimal.TEN.pow(18));
                log.warn("未找到代币配置，使用默认精度18: contractAddress={}, rawAmount={}, convertedAmount={}", 
                        contractAddress, rawTxAmount, txAmount);
            }
            
            // 更新钱包账户余额
            BigDecimal oldBalance = fromWalletAccount.getBalance() != null ? fromWalletAccount.getBalance() : BigDecimal.ZERO;
            BigDecimal newBalance = oldBalance.add(txAmount);
            fromWalletAccount.setBalance(newBalance);
            walletAccountMapper.updateById(fromWalletAccount);
            log.info("归集成功后钱包余额更新: address={}, amount={}, newBalance={}", 
                    fromAddress, txAmount, newBalance);
            
            // 发送CRM充值MQ消息
            JSONObject crmRechargeMessage = new JSONObject();
            crmRechargeMessage.put("eventCode", MqEventCode.CRM_RECHARGE_NOTIFY.getCode());
            crmRechargeMessage.put("bizRoleType", wallet.getBizRoleType());
            crmRechargeMessage.put("bizRoleTypeNo", wallet.getBizRoleTypeNo());
            crmRechargeMessage.put("tenantId", fromWalletAccount.getTenantId());
            crmRechargeMessage.put("ccy", CcyType.CNY.getCode());
            crmRechargeMessage.put("category", AccountCategory.BALANCE.getCode());
            crmRechargeMessage.put("amount", txAmount);
            // 使用实际的代币精度
            String decimalsStr = chainCoin != null && chainCoin.getCoinDecimal() != null ? 
                    chainCoin.getCoinDecimal().toString() : "2";
            crmRechargeMessage.put("decimals", decimalsStr);
            crmRechargeMessage.put("remark", "资金归集成功后的用户充值");
            crmRechargeMessage.put("txHash", collectionTxHash);
            crmRechargeMessage.put("timestamp", System.currentTimeMillis());

            rocketMQProducer.send(topic, crmRechargeMessage.toString());
            log.info("归集成功后CRM充值MQ消息发送: tenantId={}, amount={}, txHash={}", 
                    fromWalletAccount.getTenantId(), txAmount, collectionTxHash);
                    
        } catch (Exception e) {
            log.error("归集成功后CRM充值异常: txHash={}, error={}", collectionTxHash, e.getMessage(), e);
        }
    }
    
    /**
     * 从交易数据中解析代币转账金额
     * 解析ERC20 Transfer事件的logs来获取实际的转账金额
     */
    private BigDecimal parseTokenAmountFromTransaction(Transaction transaction, TransactionReceipt receipt) {
        try {
            // ERC20 Transfer事件签名: Transfer(address indexed from, address indexed to, uint256 value)
            // 动态计算事件签名的keccak256哈希值
            String transferEventSignature = calculateTransferEventSignature();
            
            if (receipt == null || receipt.getLogs() == null) {
                log.warn("交易收据或logs为空，无法解析转账金额: txHash={}", transaction.getHash());
                return null;
            }
            
            // 遍历所有logs查找Transfer事件
            for (Log logEvent : receipt.getLogs()) {
                if (logEvent.getTopics() != null && logEvent.getTopics().size() >= 3) {
                    // 检查是否是Transfer事件 (第一个topic是事件签名)
                    if (transferEventSignature.equals(logEvent.getTopics().get(0))) {
                        try {
                            // ERC20 Transfer事件标准格式:
                            // topics[0] = Transfer事件签名 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
                            // topics[1] = from地址 (indexed)
                            // topics[2] = to地址 (indexed)  
                            // data = value金额 (未indexed，存储在data字段中)
                            
                            String valueHex = logEvent.getData();
                            if (valueHex == null || valueHex.equals("0x") || valueHex.length() < 66) {
                                log.debug("Transfer事件data字段为空或无效: {}", valueHex);
                                continue; // 跳过这个log，继续查找
                            }
                            
                            // 将hex字符串转换为BigInteger
                            BigInteger amount = Numeric.toBigInt(valueHex);
                            BigDecimal amountDecimal = new BigDecimal(amount);
                            
                            log.info("解析到ERC20转账金额: txHash={}, amount={}", transaction.getHash(), amountDecimal);
                            return amountDecimal;
                            
                        } catch (Exception parseException) {
                            log.debug("解析单个Transfer事件失败，继续查找: {}", parseException.getMessage());
                            continue;
                        }
                    }
                }
            }
            
            // 如果没有找到Transfer事件，尝试从input data解析
            String input = transaction.getInput();
            if (input != null && input.length() > 138) {
                // 动态计算ERC20 transfer方法签名: transfer(address,uint256)
                String transferMethodSignature = calculateTransferMethodSignature();
                if (input.startsWith(transferMethodSignature)) {
                    try {
                        // 提取value参数 (最后32字节)
                        String valueHex = input.substring(input.length() - 64);
                        BigInteger amount = Numeric.toBigInt(valueHex);
                        BigDecimal amountDecimal = new BigDecimal(amount);
                        
                        log.info("从input data解析到ERC20转账金额: txHash={}, amount={}", transaction.getHash(), amountDecimal);
                        return amountDecimal;
                        
                    } catch (Exception inputParseException) {
                        log.debug("从input data解析失败: {}", inputParseException.getMessage());
                    }
                }
            }
            
            log.warn("未找到ERC20 Transfer事件，无法解析转账金额: txHash={}", transaction.getHash());
            return null;
            
        } catch (Exception e) {
            log.error("解析交易金额失败: txHash={}, error={}", transaction.getHash(), e.getMessage(), e);
            return null;
        }
    }

    /**
     * 通知归集失败
     */
    private void notifyFundCollectionFailureEvent(String chainIdentifier, String collectionTxHash, String errorMessage) {
        log.error("资金归集失败通知，chain: {}, txHash: {}, error: {}",
                chainIdentifier, collectionTxHash, errorMessage);
        
        // TODO: 实现具体的失败通知逻辑
        // 1. 更新数据库状态
        // 2. 发送失败回调
        // 3. 记录失败日志
        // 4. 可能需要人工介入处理

    }

    /**
     * 获取资金归集状态
     * 
     * @param chainIdentifier 链标识
     * @param txHash 交易哈希
     * @return 归集状态信息
     */
    public CollectionStatus getFundCollectionStatus(String chainIdentifier, String txHash) {
        try {
            TransactionReceipt receipt = blockchainTransactionService.getTransactionReceipt(chainIdentifier, txHash);
            if (receipt == null) {
                return CollectionStatus.PENDING;
            }
            return receipt.isStatusOK() ? CollectionStatus.SUCCESS : CollectionStatus.FAILED;
        } catch (Exception e) {
            log.error("获取归集状态失败", e);
            return CollectionStatus.UNKNOWN;
        }
    }

    /**
     * 计算ERC20 Transfer事件签名
     * Transfer(address indexed from, address indexed to, uint256 value)
     * 注意：即使参数是indexed，事件签名仍然使用标准格式 Transfer(address,address,uint256)
     */
    private String calculateTransferEventSignature() {
        try {
            // ERC20 Transfer事件的标准签名格式：Transfer(address,address,uint256)
            // indexed关键字不影响事件签名计算，只是影响日志存储方式
            String eventSignature = "Transfer(address,address,uint256)";
            
            // 使用Web3j的Hash.sha3方法计算keccak256哈希
            byte[] messageHash = Hash.sha3(eventSignature.getBytes(StandardCharsets.UTF_8));
            String signature = "0x" + Numeric.toHexString(messageHash).replaceFirst("^0x", "");
            
            log.debug("计算的Transfer事件签名: {}", signature);
            return signature;
            
        } catch (Exception e) {
            log.error("计算Transfer事件签名失败，使用默认值", e);
            // 如果计算失败，使用已知的正确值作为fallback
            return "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
        }
    }

    /**
     * 计算ERC20 transfer方法签名
     * transfer(address to, uint256 value)
     */
    private String calculateTransferMethodSignature() {
        try {
            // ERC20 transfer方法的标准签名格式：transfer(address,uint256)
            String methodSignature = "transfer(address,uint256)";
            
            // 使用方法签名计算sha3哈希的前4字节(方法选择器)
            byte[] messageHash = Hash.sha3(methodSignature.getBytes(StandardCharsets.UTF_8));
            String signature = "0x" + Numeric.toHexString(messageHash).replaceFirst("^0x", "").substring(0, 10);
            
            log.debug("计算的transfer方法签名: {}", signature);
            return signature;
            
        } catch (Exception e) {
            log.error("计算transfer方法签名失败，使用默认值", e);
            // 如果计算失败，使用已知的正确值作为fallback
            return "0xa9059cbb";
        }
    }

    /**
     * 从交易日志中获取代币合约地址
     */
    private String getTokenContractAddressFromLogs(TransactionReceipt receipt) {
        try {
            if (receipt == null || receipt.getLogs() == null) {
                return null;
            }
            
            String transferEventSignature = calculateTransferEventSignature();
            
            // 遍历所有logs查找Transfer事件
            for (Log logEvent : receipt.getLogs()) {
                if (logEvent.getTopics() != null && logEvent.getTopics().size() >= 3) {
                    // 检查是否是Transfer事件
                    if (transferEventSignature.equals(logEvent.getTopics().get(0))) {
                        String contractAddress = logEvent.getAddress();
                        if (contractAddress != null) {
                            log.debug("从Transfer事件获取代币合约地址: {}", contractAddress);
                            return contractAddress;
                        }
                    }
                }
            }
            
            return null;
            
        } catch (Exception e) {
            log.error("从交易日志获取代币合约地址失败", e);
            return null;
        }
    }

    /**
     * 资金归集状态枚举
     */
    public enum CollectionStatus {
        PENDING,    // 等待确认
        SUCCESS,    // 成功
        FAILED,     // 失败
        UNKNOWN     // 未知状态
    }
}
